<?php


namespace app\common\cachemodel;


use app\common\model\BaseCache;
use Exception;
use think\Log;
use XznsTools\cache\CacheManage;

class ZlcrAstrExerciseRecord extends BaseCache
{
    protected $table = 'wechat_backup_07_18_14_43_00.zlcr_astr_exercise_record';

    protected $cacheModel = 'astr_admin.user_result';

    protected $cacheIdKey = 'id';

    /**
     * 设置缓存
     * @param $data
     * @param $astrId
     * @param int $type 考试类型 1=>定制报告 2=>问答三合一 3=>问答星盘 4=>问答骰子 5=>问答塔罗
     * @throws Exception
     */
    public function setCacheData($data, $astrId, int $type = 1): void
    {
        CacheManage::getInstance()->setCacheConfig($this->cacheModel, $astrId . ':' . $type)->setCache($data, 'details', false);
    }

    /**
     * 删除缓存
     * @param $astrId
     * @param int $type 考试类型 1=>定制报告 2=>问答三合一 3=>问答星盘 4=>问答骰子 5=>问答塔罗
     * @throws Exception
     */
    public function rmCacheData($astrId, int $type = 1): void
    {
        CacheManage::getInstance()->setCacheConfig($this->cacheModel, $astrId . ':' . $type)->rmCache();
    }

    /**
     * 获取考核信息
     * @param int $astrId
     * @param int $type 考试类型 1=>定制报告 2=>问答三合一 3=>问答星盘 4=>问答骰子 5=>问答塔罗
     * @param array $field
     * @return array|bool|mixed|string
     * @throws Exception
     */
    public function getExerciseInfo(int $astrId, int $type = 1, array $field = [])
    {
        return CacheManage::getInstance()->setCacheConfig($this->cacheModel, $astrId . ':' . $type)
            ->getDataAndSet(function () use ($astrId, $type)
            {
                try
                {
                    $answerResult = $this->where(['astr_id' => $astrId, 'type' => $type])->order('id desc')
                        ->field('id,astr_id,level,content1,content2,content3,content4,grade1,grade2,grade3,grade4,grade,level,create_time,update_time,status,answer_time,fail_time,type')
                        ->findOrFail()->toArray();
                }
                catch (Exception $e)
                {
                    //Log::write('ZlcrAstrExerciseRecord占星师答题状态信息异常：' . $e->getMessage(), 'error', true);
                    return [];
                }

                return $answerResult;
            }, $field);
    }


    /**
     * 设置占星师培训考试信息缓存
     * @param string $cacheId
     * @param $data
     * @throws Exception
     */
    public function setPlatformExerInfoCache(string $cacheId, $data)
    {
        CacheManage::getInstance()->setCacheConfig($this->cacheModel, $cacheId)->setCacheTime(86400)->setCache($data, 'details', false);
    }

    /**
     * 获取占星师培训考试信息
     * @param string $cacheId
     * @return array|bool|string
     * @throws Exception
     */
    public function getPlatformExerInfo(string $cacheId)
    {
        return CacheManage::getInstance()->setCacheConfig($this->cacheModel, $cacheId)->getCache();
    }

    /**
     * 查看考试结果
     * @param array $astrAnswerInfo
     * @return array
     * @throws Exception
     */
    public function getExerciseRes($astrAnswerInfo = []): array
    {
        $nowTime = time();
        if ($astrAnswerInfo)
        {
            // 考试时长
            $exerciseTimeRange = [
                1 => 3600,
                2 => 3600,
                3 => 2400,
                4 => 2400,
                5 => 2400,
            ];
            $astrAnswerInfo['type'] = (int)$astrAnswerInfo['type'];
            switch ($astrAnswerInfo['level'])
            {
                case 1:
                    if ((int)$astrAnswerInfo['status'] === 2)
                    {   // 未通过
                        $nextTime = ($nowTime + 86400) - $astrAnswerInfo['fail_time']; // 距离下次考核时间
                        $status = 1;
                        $h = ceil($nextTime / 3600);
                        $tips = ($h > 24 ? 24 : $h) . '小时后重试';
                    } else
                    {   // 进行中
                        $content1 = \GuzzleHttp\json_decode($astrAnswerInfo['content1'], true);
                        if ($nowTime - $content1['start_time'] >= $exerciseTimeRange[$astrAnswerInfo['type']])   // 超时1小时
                        {   // 任务失败
                            $astrAnswerInfo['answer_time'] += $content1['max_answer_time'];
                            $astrAnswerInfo['status'] = 2;
                            $astrAnswerInfo['fail_time'] = $content1['start_time'] + $exerciseTimeRange[$astrAnswerInfo['type']];  // 任务失败时间
                            // 更新
                            $astrAnswerModel = new ZlcrAstrExerciseRecord();
                            if (isset($astrAnswerInfo['id']))
                            {
                                $astrAnswerModel->where('id', $astrAnswerInfo['id'])->update([
                                    'update_time' => $nowTime,
                                    'content1' => $astrAnswerInfo['content1'],
                                    'answer_time' => $astrAnswerInfo['answer_time'],
                                    'fail_time' => $astrAnswerInfo['fail_time'],
                                    'status' => $astrAnswerInfo['status'],
                                ]);
                            } else
                            {
                                $id = $astrAnswerModel->insertGetId($astrAnswerInfo);
                                $astrAnswerInfo['id'] = $id;
                            }

                            $astrAnswerModel->setCacheData($astrAnswerInfo, (int)$astrAnswerInfo['astr_id'], $astrAnswerInfo['type']); // 更新缓存

                            $tim = $astrAnswerInfo['fail_time'] + 86400 - $nowTime;
                            // 判断失败时间距离现在是否满足24小时
                            if ($tim > 0)
                            {   // 不满足24小时
                                $status = 1;
                                $h = ceil($tim / 3600);
                                $tips = ($h > 24 ? 24 : $h) . '小时后重试';
                            } else
                            {   // 满足24小时 重新从头开始考试
                                $status = 0;
                                $tips = '';
                            }
                        } else
                        {
                            $status = 4;
                            $tips = '进行中';
                        }
                    }

                    $resData[1] = [
                        'status' => $status,
                        'tips' => $tips,
                    ];

                    if ($astrAnswerInfo['type'] === 1)
                    {
                        $resData[2] = [
                            'status' => -1,
                            'tips' => '',
                        ];
                    }

                    return $resData;
                    break;
                default: // 笔试
                    // 判断 是否在进行中
                    if ($astrAnswerInfo['content2'])
                    {   // 进行中
                        // 判断任务是否失败
                        $content2 = \GuzzleHttp\json_decode($astrAnswerInfo['content2'], true);
                        if ($content2['answer'])
                        {   // 已经回答过了 等待审核
                            if ((int)$astrAnswerInfo['status'] === 2)
                            {
                                $nextTime = ($nowTime + 86400) - $astrAnswerInfo['fail_time']; // 距离下次考核时间
                                $status = 1;
                                $h = ceil($nextTime / 3600);
                                $tips = ($h > 24 ? 24 : $h) . '小时后重试';
                            } else
                            {
                                $status = 3;
                                $tips = '等待审核';
                            }
                        } else
                        {
                            // 判断任务是否已过期
                            if (($nowTime - $content2['start_time']) >= $content2['max_answer_time'])
                            {   // 任务过期 将任务状态改为过期
                                $content2['answer'] = [
                                    'answer_time' => $content2['max_answer_time'],
                                    'option' => '',
                                    'start_time' => date('Y-m-d H:i:s', $content2['start_time']),
                                ];
                                $astrAnswerInfo['content2'] = \GuzzleHttp\json_encode($content2, JSON_UNESCAPED_UNICODE);
                                $astrAnswerInfo['answer_time'] += $content2['max_answer_time'];
                                $astrAnswerInfo['status'] = 2;
                                $astrAnswerInfo['fail_time'] = $content2['start_time'] + $content2['max_answer_time'];
                                // 更新
                                $astrAnswerModel = new ZlcrAstrExerciseRecord();
                                $astrAnswerModel->where('id', $astrAnswerInfo['id'])->update([
                                    'update_time' => $nowTime,
                                    'content2' => $astrAnswerInfo['content2'],
                                    'answer_time' => $astrAnswerInfo['answer_time'],
                                    'fail_time' => $astrAnswerInfo['fail_time'],
                                    'status' => $astrAnswerInfo['status'],
                                    'level' => $astrAnswerInfo['level']
                                ]);
                                $astrAnswerModel->setCacheData($astrAnswerInfo, (int)$astrAnswerInfo['astr_id'], $astrAnswerInfo['type']); // 更新缓存

                                $tim = $astrAnswerInfo['fail_time'] + 86400 - $nowTime;
                                // 判断失败时间距离现在是否满足24小时
                                if ($tim > 0)
                                {   // 不满足24小时

                                    $status = 1;
                                    $h = ceil($tim / 3600);
                                    $tips = ($h > 24 ? 24 : $h) . '小时后重试';
                                } else
                                {   // 满足24小时 重新从头开始考试
                                    return [
                                        1 => [
                                            'status' => 0,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                                            'tips' => '',
                                        ],
                                        2 => [
                                            'status' => -1,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                                            'tips' => '',
                                        ]
                                    ];
                                }
                            } else
                            {   // 还未过期
                                $status = 4;
                                $tips = '进行中';
                            }
                        }
                    } else
                    {   // 未开始 待考核
                        $status = 0;
                        $tips = '';
                    }

                    return [
                        1 => [
                            'status' => 2,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                            'tips' => '',
                        ],
                        2 => [
                            'status' => $status,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                            'tips' => $tips,
                        ]
                    ];
            }
        }

        return [
            1 => [
                'status' => 0,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                'tips' => '',
            ],
            2 => [
                'status' => -1,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                'tips' => '',
            ]
        ];
    }

    /**
     * 查看考试结果 新  增加面试版本
     * @param array $astrAnswerInfo
     * @return array
     * @throws Exception
     */
    public function getExerciseRes2($astrAnswerInfo = []): array
    {
        $nowTime = time();
        if ($astrAnswerInfo && (int)$astrAnswerInfo['level'] === 1 && (int)$astrAnswerInfo['status'] === 2 && $nowTime - $astrAnswerInfo['fail_time'] > 86400)
        {   // 第一关未通过   24小时可以重新考试
            $astrAnswerInfo = null; // 失败24小时后允许重新考试
        }

        if ($astrAnswerInfo)
        {
            if ((int)$astrAnswerInfo['level'] === 1 && (int)$astrAnswerInfo['status'] === 2 && time() - $astrAnswerInfo['fail_time'] > 86400)
            {   // 第一关未通过   24小时可以重新考试
                $astrAnswerInfo = null; // 失败24小时后允许重新考试
            }
            if ((int)$astrAnswerInfo['level'] === 2 && (int)$astrAnswerInfo['status'] === 2)
            {   // 在第二关 考核失败
                $content2 = \GuzzleHttp\json_decode($astrAnswerInfo['content2'], true);
                if (isset($content2['interview']))
                {   // 新版本 面试失败
                    $agianDays = $content2['interview']['agian_days'] ?? 7;
                    if ($nowTime - $astrAnswerInfo['fail_time'] > 86400 * $agianDays)
                    {
                        $astrAnswerInfo = null;
                    }
                } else
                {   // 老用户
                    if (time() - $astrAnswerInfo['fail_time'] > 86400)
                    {   // 考试失败一天可以重试
                        $astrAnswerInfo = null;
                    }
                }
            }
        }

        if ($astrAnswerInfo)
        {
            // 考试时长
            $exerciseTimeRange = [  // 仅第一关 选择题
                1 => 3600,
                2 => 3600,
                3 => 2400,
                4 => 2400,
                5 => 2400,
            ];
            $astrAnswerInfo['type'] = (int)$astrAnswerInfo['type'];
            switch ($astrAnswerInfo['level'])
            {
                case 1:
                    if ((int)$astrAnswerInfo['status'] === 2)
                    {   // 未通过
                        $nextTime = $astrAnswerInfo['fail_time'] + 86400 - $nowTime; // 距离下次考核时间
                        $status = 1;
                        $h = ceil($nextTime / 3600);
                        $tips = ($h > 24 ? 24 : $h) . '小时后重试';
                    } else
                    {   // 进行中
                        $content1 = \GuzzleHttp\json_decode($astrAnswerInfo['content1'], true);
                        if ($nowTime - $content1['start_time'] >= $exerciseTimeRange[$astrAnswerInfo['type']])   // 超时1小时
                        {   // 任务失败
                            $astrAnswerInfo['answer_time'] += $content1['max_answer_time'];
                            $astrAnswerInfo['status'] = 2;
                            $astrAnswerInfo['fail_time'] = $content1['start_time'] + $exerciseTimeRange[$astrAnswerInfo['type']];  // 任务失败时间
                            // 更新
                            $astrAnswerModel = new ZlcrAstrExerciseRecord();
                            if (isset($astrAnswerInfo['id']))
                            {
                                $astrAnswerModel->where('id', $astrAnswerInfo['id'])->update([
                                    'update_time' => $nowTime,
                                    'content1' => $astrAnswerInfo['content1'],
                                    'answer_time' => $astrAnswerInfo['answer_time'],
                                    'fail_time' => $astrAnswerInfo['fail_time'],
                                    'status' => $astrAnswerInfo['status'],
                                ]);
                            } else
                            {
                                $id = $astrAnswerModel->insertGetId($astrAnswerInfo);
                                $astrAnswerInfo['id'] = $id;
                            }

                            $astrAnswerModel->setCacheData($astrAnswerInfo, (int)$astrAnswerInfo['astr_id'], $astrAnswerInfo['type']); // 更新缓存

                            $tim = $astrAnswerInfo['fail_time'] + 86400 - $nowTime;
                            // 判断失败时间距离现在是否满足24小时
                            if ($tim > 0)
                            {   // 不满足24小时
                                $status = 1;
                                $h = ceil($tim / 3600);
                                $tips = ($h > 24 ? 24 : $h) . '小时后重试';
                            } else
                            {   // 满足24小时 重新从头开始考试
                                $status = 0;
                                $tips = '';
                            }
                        } else
                        {
                            $status = 4;
                            $tips = '';
                        }
                    }

                    $resData[1] = [
                        'status' => $status,
                        'tips' => $tips,
                    ];
                    $resData[2] = [
                        'status' => -1,
                        'tips' => '',
                    ];
                    $resData['is_reset'] = $astrAnswerInfo ? false : true;
                    return $resData;
                    break;
                default: // 笔试
                    // 判断 是否在进行中
                    if ($astrAnswerInfo['content2'])
                    {   // 进行中
                        // 判断任务是否失败
                        $content2 = \GuzzleHttp\json_decode($astrAnswerInfo['content2'], true);
                        // $content2['interview'] = [
                        //     'status' => 0,  // 面试申请状态  0未申请 1=>已申请 2=>面试中 3=>面试未通过  4=>面试已通过
                        //     'interview_id' => 0, // 面试ID
                        //     'agian_days' => 0,// 下次面试天数
                        // ];
                        if (isset($content2['interview']))
                        {   // 面试信息
                            switch ($content2['interview']['status'])
                            {
                                case 1:
                                    $status = 4;
                                    $tips = '';
                                    break;
                                case 2:
                                    $status = 5;
                                    $tips = '';
                                    break;
                                case 3:
                                    $status = 1;    // -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过 3=》审核中 4=>进行中【 如果是 面试是：已申请】5=>面试中
                                    $agianDays = $content2['interview']['agian_days'] ?? 7;
                                    $nextTime = $astrAnswerInfo['fail_time'] + 86400 * $agianDays - $nowTime; // 距离下次考核时间
                                    if ($nextTime > 86400)
                                    {
                                        $h = ceil($nextTime / 86400);
                                        $tips = $h . '天后重试';
                                    } else
                                    {
                                        $h = ceil($nextTime / 3600);
                                        $tips = ($h > 24 ? 24 : $h) . '小时后重试';
                                    }
                                    break;
                                case 4:
                                    $status = 2;
                                    $tips = '';
                                    break;
                                default:
                                    $status = 0;
                                    $tips = '';
                            }
                        } else
                        {   // 没有面试信息 但是参与过旧版本 简答题
                            if ((int)$astrAnswerInfo['status'] === 2)
                            {
                                $nextTime = $astrAnswerInfo['fail_time'] + 86400 - $nowTime; // 距离下次考核时间
                                $status = 1;
                                $h = ceil($nextTime / 3600);
                                $tips = ($h > 24 ? 24 : $h) . '小时后重试';
                            } else
                            {
                                $status = 0;
                                $tips = '';
                            }
                        }
                    } else
                    {   // 未开始 待考核
                        $status = 0;
                        $tips = '';
                    }

                    return [
                        1 => [
                            'status' => 2,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                            'tips' => '',
                        ],
                        2 => [
                            'status' => $status,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                            'tips' => $tips,
                        ],
                        'is_reset' => $astrAnswerInfo ? false : true
                    ];
            }
        }

        return [
            1 => [
                'status' => 0,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                'tips' => '',
            ],
            2 => [
                'status' => -1,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                'tips' => '',
            ],
            'is_reset' => $astrAnswerInfo ? false : true
        ];
    }

    /**
     * 占星师 认证通过
     * @param array $astrInfo
     * @param int $type
     */
    public function astrExercisePass(array $astrInfo, int $type)
    {
        $astrInfo['auth_status'];
        $data = [];
        switch ($type)
        {
            case 1:
                $data['astr_level'] = 1;
                $data['astro2_level'] = 1;
                $astrInfo['auth_status']['custom_report'] = 1;
                $astrInfo['auth_status']['question_answer_astr'] = 1;
                break;
            case 2:
                $data['astro2_level'] = 1;
                $data['dice_level'] = 1;
                $data['tarot_level'] = 1;
                $astrInfo['auth_status']['question_answer_astr'] = 1;
                $astrInfo['auth_status']['question_answer_dice'] = 1;
                $astrInfo['auth_status']['question_answer_tarot'] = 1;
                break;
            case 3: // 问答-星盘
                $data['astro2_level'] = 1;
                $astrInfo['auth_status']['question_answer_astr'] = 1;
                break;
            case 4: // 问答-骰子
                $data['dice_level'] = 1;
                $astrInfo['auth_status']['question_answer_dice'] = 1;
                break;
            case 5: // 问答-塔罗
                $data['tarot_level'] = 1;
                $astrInfo['auth_status']['question_answer_tarot'] = 1;
                break;
        }

        $data['auth_status'] = json_encode($astrInfo['auth_status'], JSON_UNESCAPED_UNICODE);

        if ($astrInfo['check_status'] < 20)
        {
            $data['check_status'] = 20;
        }

        (new ZlcrAstr())->UpdateData($astrInfo['id'], ['id' => $astrInfo['id']], $data);
    }
}
